﻿// Copyright richyp 2009
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Richyp.Bodger {
    public class CodexEntry {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public string AltCategory { get; set; }
        public bool Special { get; set; }
        private List<Upgrade> unitWideUpgrades = new List<Upgrade>();
        public List<Upgrade> UnitWideUpgrades {
            get {
                return this.unitWideUpgrades;
            }
        }

        private List<Unit> units = new List<Unit>();
        public List<Unit> Units {
            get {
                return this.units;
            }
        }

        public Unit GetUnitByName(string name) {
            foreach (Unit unit in this.units) {
                if (unit.Name.ToUpper() == name.ToUpper()) {
                    return unit;
                }
            }
            return null;
        }

        public Unit GetUnitByID(int id) {
            foreach (Unit unit in this.units) {
                if (unit.ID == id) {
                    return unit;
                }
            }
            return null;
        }

        public Unit this[string name] {
            get {
                return this.GetUnitByName(name);
            }
        }

        public Unit this[int id] {
            get {
                return this.GetUnitByID(id);
            }
        }

        private int costOffset = 0;
        public int CostOffset {
            get {
                return this.costOffset;
            }
            set {
                this.costOffset = value;
            }
        }
        private int height = 60;
        public int Height {
            get { return this.height; }
            set { this.height = value; }
        }

        private bool splitOnEntries = true;
        public bool SplitOnEntries {
            get {
                return this.splitOnEntries;
            }
            set {
                this.splitOnEntries = value;
            }
        }
        public static CodexEntry CreateFromNode(CodexFile codexFile, XmlNode node) {
            CodexEntry entry = new CodexEntry();
            foreach (XmlAttribute attr in node.Attributes) {
                if (attr.Name.ToUpper() == "OVERRIDEENTRYHEIGHT") {
                    entry.height = int.Parse(attr.Value);
                } else if (attr.Name.ToUpper() == "SPLITONUNITS") {
                    entry.splitOnEntries = bool.Parse(attr.Value);
                }
            } 
            entry.Special = false;
            foreach (XmlNode childNode in node.ChildNodes) {
                string name = childNode.Name.ToUpper();
                string value = childNode.InnerText;
                if (name == "ID") {
                    entry.ID = int.Parse(value);
                } else if (name == "NAME") {
                    entry.Name = value;
                } else if (name == "CATEGORY") {
                    entry.Category = value;
                } else if (name == "ALTCATEGORY") {
                    entry.AltCategory = value;
                } else if( name == "SPECIAL" ) {
                    entry.Special = bool.Parse(value);
                } else if( name == "COSTOFFSET" ) {
                    entry.costOffset = int.Parse(value);                
                } else if( name == "TRANSPORTS" ) {
                    foreach (XmlNode transportNode in childNode.ChildNodes) {
                        if (transportNode.Name.ToUpper() == "TRANSPORT") {
                            Unit unit = codexFile.GetTransportByName(transportNode.InnerText);
                            if (unit == null) {
                                throw new Exception("Failed to find transport: " + transportNode.InnerText);
                            } else {
                                Unit copy = Unit.Copy(unit);
                                entry.units.Add(unit);
                            }
                        }
                    }
                } else if( name == "UNITWIDEUPGRADES" ) {
                    foreach (XmlNode upgradeNode in childNode.ChildNodes) {
                        string upgradeName = upgradeNode.Name.ToUpper();
                       
                        if (upgradeName == "NAMEDENTRY") {
                            Upgrade upgrade = new Upgrade();
                            string[] parts = upgradeNode.InnerText.Split(new char[] { ',' });
                            upgrade.Wargear = codexFile.GetWargearByName(parts[0]);
                            if (upgrade.Wargear == null) {
                                throw new Exception("Wargear not found: " + parts[0] + " in entry: " + entry.Name);
                            }

                            if (parts.Length > 1) {
                                upgrade.Cost = int.Parse(parts[1]);
                            }
                            foreach (XmlAttribute attr in upgradeNode.Attributes) {
                                if (attr.Name.ToUpper() == "COSTPERSQUAD") {
                                    upgrade.CostPerSquad = bool.Parse(attr.Value);
                                } else if (attr.Name.ToUpper() == "UPGRADECOST") {
                                    upgrade.Cost = int.Parse(attr.Value);
                                }
                            }
                            entry.UnitWideUpgrades.Add(upgrade);
                            Console.WriteLine(
                                "Added unitwide upgrade:" + upgrade.Wargear.Name + " to " + 
                                entry.Name + " cost " + upgrade.Cost
                                );
                        }
                    }
                } else if (name == "CONTAINS") {
                    foreach (XmlNode unitTypeNode in childNode.ChildNodes) {
                        if (unitTypeNode.Name.ToUpper() == "UNITTYPE") {
                            Unit unit = Unit.CreateFromNode(codexFile, unitTypeNode);
                            entry.units.Add(unit);
                        }
                    }
                }
            }
            return entry;
        }

        public int BaseCost {
            get {
                int total = 0;
                foreach (Unit unit in this.Units) {
                    total += unit.BaseCost;
                }
                return total;
            }
        }
    }
}
